#include "ExportFileService.h"

ExportFileService::ExportFileService()
{
}

bool ExportFileService::init(QString ID,QString mingCheng,QString path)
{
    //    filename = path+ID+"_"+mingCheng+".xls";
    filename = path+mingCheng+".xls"; // 不加实验id的导出文件名称
    BasicExcel e;
    QTextCodec *code = QTextCodec::codecForName("gbk");
    name = code->fromUnicode(filename).data();

    //创建四个工作表
    e.New(4);
    //保存文件
    if(!e.SaveAs(name.c_str()))
    {
        return false;
    }
    return true;


    QAxObject excel("Excel.Application");
    excel.setProperty("Visible", false);
    QAxObject * workbooks = excel.querySubObject("WorkBooks");
    if (!workbooks)  return false;    //错误返回

    workbooks->dynamicCall("Add"); //新建一个工作簿
    QAxObject * workbook = excel.querySubObject("ActiveWorkBook"); //获取当前工作簿
    workbook->dynamicCall("SaveAs (const QString&)", QString(filename));

}


bool ExportFileService::yangben2EXCEL(QList<QString> info,Sample sampleList[96],Target targetList[96][20])
{
    BasicExcel e;
    if(!e.Load(name.c_str()))
    {
        return false;
    }
    unsigned int start = 0;
    //新建表单6
    BasicExcelWorksheet* sheet = e.GetWorksheet(start);

    //将工作表命名
    sheet->Rename(reinterpret_cast<const wchar_t *>(QString("样本设置").utf16()));

    vector<QString> attribute1 ={"设备名称","设备型号","设备序列号","信号平滑","创建日期",
                                 "参比荧光","实验名称","实验文件名","实验编码","实验注释",
                                 "实验类型","实验运行结束时间","用户名","读后阶段/步骤数",
                                 "量化循环数方法","预读阶段/步骤数"
                                };


    BasicExcelCell* cell;
    int len1 = attribute1.size();

    //1、插入基本信息的表头
    for (int i=0 ; i<len1; i++)
    {
        cell = sheet->Cell(i,0);
        cell->SetWString(reinterpret_cast<const wchar_t *>(attribute1[i].utf16()));
    }

    vector<QString> attribute2 ={"反应孔","反应孔位置","样本名","样本颜色","基因名称",
                                 "基因颜色","样本类型","报告基团","萃灭基团","数量","注释"
                                };
    int len2 = attribute2.size();

    //2、插入反应板的表头
    for(int i=0; i<len2; i++)
    {
        cell = sheet->Cell(len1+1,i);
        cell->SetWString(reinterpret_cast<const wchar_t *>(attribute2[i].utf16()));
    }

    //3、插入基本信息
    if(info.size() != 0)
    {

        for (int i=0 ; i<len1 ; i++)
        {
            cell = sheet->Cell(i,1);
            cell->SetWString(reinterpret_cast<const wchar_t *>(info[i].utf16()));
        }

    }


    //4、插入反应板数据

    //获取反应板信息

    reactionInfo = disposeReactionWells(sampleList,targetList);

    int len3 = reactionInfo.size();

    for (int i=0; i<len3; i++)
    {
        cell = sheet->Cell(len1+2+i,0);
        cell->SetWString(reinterpret_cast<const wchar_t *>(reactionInfo[i].value("num").utf16()));

        cell = sheet->Cell(len1+2+i,1);
        cell->SetWString(reinterpret_cast<const wchar_t *>(reactionInfo[i].value("place").utf16()));

        cell = sheet->Cell(len1+2+i,2);
        cell->SetWString(reinterpret_cast<const wchar_t *>(reactionInfo[i].value("sampleName").utf16()));

        cell = sheet->Cell(len1+2+i,3);
        cell->SetWString(reinterpret_cast<const wchar_t *>(reactionInfo[i].value("sampleColor").utf16()));

        cell = sheet->Cell(len1+2+i,4);
        cell->SetWString(reinterpret_cast<const wchar_t *>(reactionInfo[i].value("targetName").utf16()));

        cell = sheet->Cell(len1+2+i,5);
        cell->SetWString(reinterpret_cast<const wchar_t *>(reactionInfo[i].value("targetColor").utf16()));

        cell = sheet->Cell(len1+2+i,6);
        cell->SetWString(reinterpret_cast<const wchar_t *>(reactionInfo[i].value("task").utf16()));

        cell = sheet->Cell(len1+2+i,7);
        cell->SetWString(reinterpret_cast<const wchar_t *>(reactionInfo[i].value("reporter").utf16()));

        cell = sheet->Cell(len1+2+i,8);
        cell->SetWString(reinterpret_cast<const wchar_t *>(reactionInfo[i].value("quencher").utf16()));

        cell = sheet->Cell(len1+2+i,9);
        cell->SetWString(reinterpret_cast<const wchar_t *>(reactionInfo[i].value("quantity").utf16()));

        cell = sheet->Cell(len1+2+i,10);
        cell->SetWString(reinterpret_cast<const wchar_t *>(reactionInfo[i].value("explain").utf16()));

        // 休眠
        this->sleep(EXPORT_SLEEP_TIME);
    }

    //保存文件
    if(!e.SaveAs(name.c_str()))
    {
        return false;
    }

    return true;
}

bool ExportFileService::yuanshi2EXCEL(QList<QString> info,QList<QList<QHash<QString, QString>>> yingGuangData)
{
    //打开相应名称的xls
    BasicExcel e;
    if(!e.Load(name.c_str()))
    {
        return  false;
    }

    // 操纵第4个sheet页
    unsigned int start = 3;
    BasicExcelWorksheet* sheet = e.GetWorksheet(start);
    //将工作表命名
    sheet->Rename(reinterpret_cast<const wchar_t *>(QString("原始数据").utf16()));

    BasicExcelCell* cell;

    //1、插入基本信息的表头
    vector<QString> attribute1 ={"设备名称","设备型号","设备序列号","信号平滑化","创建日期",
                                 "参比荧光","实验名称","实验文件名","实验编码","实验注释",
                                 "实验类型","实验运行结束时间","用户名","读后阶段/步骤数",
                                 "量化循环数方法","预读阶段/步骤数"
                                };

    int len1 = attribute1.size();
    for (int i=0 ; i<len1; i++)
    {
        cell = sheet->Cell(i,0);
        cell->SetWString(reinterpret_cast<const wchar_t *>(attribute1[i].utf16()));
    }


    //2、插入反应板的表头
    vector<QString> attribute2 ={"反应孔","反应孔位置", "循环数",
                                 "FAM","VIC","ROX","CY5",
                                 "x5","x6","x7","x8"
                                };
    int len2 = attribute2.size();
    for(int i=0; i<len2; i++)
    {
        cell = sheet->Cell(len1+1,i);
        cell->SetWString(reinterpret_cast<const wchar_t *>(attribute2[i].utf16()));
    }

    //3、插入基本信息数据

    if(info.size() != 0)
    {
        for (int i=0 ; i<len1 ; i++)
        {
            cell = sheet->Cell(i,1);
            cell->SetWString(reinterpret_cast<const wchar_t *>(info[i].utf16()));
        }
    }

    //4、插入反应孔的应该值

    if(yingGuangData.size() != 0)
    {

        int rows = len1+2;     //反应板插入数据的行数
        int cycles_number = 1; //定义循环数

        QList <QString>reactionPlace;  //定义反应孔

        if(yingGuangData[0].size() == 32)
        {
            reactionPlace = reactionPlace32;
        }
        else if(yingGuangData[0].size() == 16)
        {
            reactionPlace = reactionPlace16;
        }

        LOG << "原始荧光导出开始";

        for(int index=0; index<yingGuangData.size(); index++)
        {
            int reaction_number = 0;   //定义反应孔数 1~96

            //将第二层qlist中的数据按照A1~A12的顺序插入
            for (int i=0; i<8; i++)
            {
                for (int j=i; j<yingGuangData[0].size(); j+=8)
                {
                    //插入反应孔
                    cell = sheet->Cell(rows,0);
                    cell->SetWString(reinterpret_cast<const wchar_t *>(QString::number(reaction_number+1).utf16()));

                    //插入反应孔位置
                    cell = sheet->Cell(rows,1);
                    cell->SetWString(reinterpret_cast<const wchar_t *>(reactionPlace[reaction_number].utf16()));

                    //插入循环数
                    cell = sheet->Cell(rows,2);
                    cell->SetWString(reinterpret_cast<const wchar_t *>(QString::number(cycles_number).utf16()));

                    //插入FAM
                    cell = sheet->Cell(rows,3);
                    cell->SetWString(reinterpret_cast<const wchar_t *>(yingGuangData[index][j].value("1").utf16()));

                    //插入VIC
                    cell = sheet->Cell(rows,4);
                    cell->SetWString(reinterpret_cast<const wchar_t *>(yingGuangData[index][j].value("2").utf16()));

                    //插入CY5
                    cell = sheet->Cell(rows,5);
                    cell->SetWString(reinterpret_cast<const wchar_t *>(yingGuangData[index][j].value("3").utf16()));

                    //插入ROX
                    cell = sheet->Cell(rows,6);
                    cell->SetWString(reinterpret_cast<const wchar_t *>(yingGuangData[index][j].value("4").utf16()));

                    //插入x5
                    cell = sheet->Cell(rows,7);
                    cell->SetWString(reinterpret_cast<const wchar_t *>(QString("0").utf16()));

                    //插入x6
                    cell = sheet->Cell(rows,8);
                    cell->SetWString(reinterpret_cast<const wchar_t *>(QString("0").utf16()));

                    //插入x7
                    cell = sheet->Cell(rows,9);
                    cell->SetWString(reinterpret_cast<const wchar_t *>(QString("0").utf16()));

                    //插入x8
                    cell = sheet->Cell(rows,10);
                    cell->SetWString(reinterpret_cast<const wchar_t *>(QString("0").utf16()));


                    //每插入完一行后将rows加1
                    rows++;
                    //每插入完一行将reaction_number加1
                    reaction_number++;
                }

            }
            //每完成一轮外层循环，循环数加1
            cycles_number++;

            // 休眠
            this->sleep(EXPORT_SLEEP_TIME);
        }

    }

    LOG << "原始荧光导出结束";

    //保存文件
    if(!e.SaveAs(name.c_str()))
    {
        return false;
    }
    return  true;



}

bool ExportFileService::yingguang2EXCEL(QList<QString> info,QList<QList<QHash<QString, QString>>> yingGuangData)
{

    //打开相应名称的xls
    BasicExcel e;
    if(!e.Load(name.c_str()))
    {
        return  false;
    }

    unsigned int start = 1;
    BasicExcelWorksheet* sheet = e.GetWorksheet(start);
    //将工作表命名
    sheet->Rename(reinterpret_cast<const wchar_t *>(QString("拟合数据").utf16()));

    BasicExcelCell* cell;

    //1、插入基本信息的表头
    vector<QString> attribute1 ={"设备名称","设备型号","设备序列号","信号平滑化","创建日期",
                                 "参比荧光","实验名称","实验文件名","实验编码","实验注释",
                                 "实验类型","实验运行结束时间","用户名","读后阶段/步骤数",
                                 "量化循环数方法","预读阶段/步骤数"
                                };

    int len1 = attribute1.size();
    for (int i=0 ; i<len1; i++)
    {
        cell = sheet->Cell(i,0);
        cell->SetWString(reinterpret_cast<const wchar_t *>(attribute1[i].utf16()));
    }


    //2、插入反应板的表头
    vector<QString> attribute2 ={"反应孔","反应孔位置", "循环数",
                                 "FAM","VIC","ROX","CY5",
                                 "x5","x6","x7","x8"
                                };
    int len2 = attribute2.size();
    for(int i=0; i<len2; i++)
    {
        cell = sheet->Cell(len1+1,i);
        cell->SetWString(reinterpret_cast<const wchar_t *>(attribute2[i].utf16()));
    }

    //3、插入基本信息数据

    if(info.size() != 0)
    {
        for (int i=0 ; i<len1 ; i++)
        {
            cell = sheet->Cell(i,1);
            cell->SetWString(reinterpret_cast<const wchar_t *>(info[i].utf16()));
        }
    }

    //4、插入反应孔的应该值

    if(yingGuangData.size() != 0)
    {

        int rows = len1+2;     //反应板插入数据的行数
        int cycles_number = 1; //定义循环数

        QList <QString>reactionPlace;  //定义反应孔

        if(yingGuangData[0].size() == 32)
        {
            reactionPlace = reactionPlace32;
        }
        else if(yingGuangData[0].size() == 16)
        {
            reactionPlace = reactionPlace16;
        }

        LOG << "拟合荧光导出开始";

        for(int index=0; index<yingGuangData.size(); index++)
        {
            int reaction_number = 0;   //定义反应孔数 1~96

            //将第二层qlist中的数据按照A1~A12的顺序插入
            for (int i=0; i<8; i++)
            {
                for (int j=i; j<yingGuangData[0].size(); j+=8)
                {
                    //插入反应孔
                    cell = sheet->Cell(rows,0);
                    cell->SetWString(reinterpret_cast<const wchar_t *>(QString::number(reaction_number+1).utf16()));

                    //插入反应孔位置
                    cell = sheet->Cell(rows,1);
                    cell->SetWString(reinterpret_cast<const wchar_t *>(reactionPlace[reaction_number].utf16()));

                    //插入循环数
                    cell = sheet->Cell(rows,2);
                    cell->SetWString(reinterpret_cast<const wchar_t *>(QString::number(cycles_number).utf16()));

                    //插入FAM
                    cell = sheet->Cell(rows,3);
                    cell->SetWString(reinterpret_cast<const wchar_t *>(QString::number(yingGuangData[index][j].value("1").toFloat(), 'f', 0).utf16()));

                    //插入VIC
                    cell = sheet->Cell(rows,4);
                    cell->SetWString(reinterpret_cast<const wchar_t *>(QString::number(yingGuangData[index][j].value("2").toFloat(), 'f', 0).utf16()));

                    //插入CY5
                    cell = sheet->Cell(rows,5);
                    cell->SetWString(reinterpret_cast<const wchar_t *>(QString::number(yingGuangData[index][j].value("3").toFloat(), 'f', 0).utf16()));

                    //插入ROX
                    cell = sheet->Cell(rows,6);
                    cell->SetWString(reinterpret_cast<const wchar_t *>(QString::number(yingGuangData[index][j].value("4").toFloat(), 'f', 0).utf16()));

                    //插入x5
                    cell = sheet->Cell(rows,7);
                    cell->SetWString(reinterpret_cast<const wchar_t *>(QString("0").utf16()));

                    //插入x6
                    cell = sheet->Cell(rows,8);
                    cell->SetWString(reinterpret_cast<const wchar_t *>(QString("0").utf16()));

                    //插入x7
                    cell = sheet->Cell(rows,9);
                    cell->SetWString(reinterpret_cast<const wchar_t *>(QString("0").utf16()));

                    //插入x8
                    cell = sheet->Cell(rows,10);
                    cell->SetWString(reinterpret_cast<const wchar_t *>(QString("0").utf16()));


                    //每插入完一行后将rows加1
                    rows++;
                    //每插入完一行将reaction_number加1
                    reaction_number++;

                }

            }
            //每完成一轮外层循环，循环数加1
            cycles_number++;

            // 休眠
            this->sleep(EXPORT_SLEEP_TIME);
        }

    }

    LOG << "拟合荧光导出结束";

    //保存文件
    if(!e.SaveAs(name.c_str()))
    {
        return false;
    }
    return  true;

}

bool ExportFileService::kuozeng2EXCEL(QList<QString> info,QList<QList<QHash<QString, QString>>> yingGuangData,QHash<QString,QString> targetTable, QList<QString> ct)
{

    //打开相应名称的xls
    BasicExcel e;

    if(!e.Load(name.c_str()))
    {
        return false;
    }

    LOG << "ct导出之前";
    //    LOG << "export" << ct << ct.size();

    unsigned int start = 2;
    BasicExcelWorksheet* sheet = e.GetWorksheet(start);
    //将工作表命名
    sheet->Rename(reinterpret_cast<const wchar_t *>(QString("扩增数据").utf16()));

    BasicExcelCell* cell;

    //1、插入基本信息的表头
    vector<QString> attribute1 ={"设备名称","设备型号","设备序列号","信号平滑","创建日期",
                                 "参比荧光","实验名称","实验文件名","实验编码","实验注释",
                                 "实验类型","实验运行结束时间","用户名","读后阶段/步骤数",
                                 "量化循环数方法","预读阶段/步骤数"
                                };
    int len1 = attribute1.size();
    for (int i=0 ; i<len1; i++)
    {
        cell = sheet->Cell(i,0);
        cell->SetWString(reinterpret_cast<const wchar_t *>(attribute1[i].utf16()));
    }

    //2、插入反应板的表头
    vector<QString> attribute2 ={"反应孔","反应孔位置",
                                 "循环数","基因名称",
                                 "Rn","ΔRn","Ct"
                                };
    int len2 = attribute2.size();
    for(int i=0; i<len2; i++)
    {
        cell = sheet->Cell(len1+1,i);
        cell->SetWString(reinterpret_cast<const wchar_t *>(attribute2[i].utf16()));
    }



    //3、插入基本信息数据
    if(info.size() != 0)
    {
        for (int i=0 ; i<len1 ; i++)
        {
            cell = sheet->Cell(i,1);
            cell->SetWString(reinterpret_cast<const wchar_t *>(info[i].utf16()));
        }
    }


    //4、插入反应板数据

    //处理ct数据
    vector<vector<QString>> ctInfo;
    QHash<QString,int> Target_number = {{"Target1",0},{"Target2",1},{"Target3",2},{"Target3",3}};

    if(ct.size() != 0)
    {
        int ctStep = ct.size()/4;
        for (int i=0; i<ctStep; i++)
        {
            vector<QString> tmp;
            for (int j=0; j<4; j++)
            {
                tmp.push_back(ct[(i*4)+j]) ;
            }
            ctInfo.push_back(tmp);
        }
    }

    if(yingGuangData.size() != 0)
    {

        QList<QList<QHash<QString, QString>>> kuozengData; //将荧光数据按照反应孔位置存储

        for ( int reaction_number=0; reaction_number<yingGuangData[0].size(); reaction_number++)
        {
            QList<QHash<QString, QString>> cycles_temp;    //用来存储某一个孔位的多次循环信息

            for ( int cycles_times=0; cycles_times<yingGuangData.size(); cycles_times++)
            {
                //第cycles_times循环reaction_number孔位的荧光值
                cycles_temp.append(yingGuangData[cycles_times][reaction_number]);
            }
            //将这个孔位的多次循环信息存到kuozengData里面
            kuozengData.append(cycles_temp);
        }

        int rows = len1+2; //定义行位置
        QList <QString>reactionPlace;  //定义反应孔

        if(yingGuangData[0].size() == 32)
        {
            reactionPlace = reactionPlace32;
        }
        else if(yingGuangData[0].size() == 16)
        {
            reactionPlace = reactionPlace16;
        }

        vector<QString>test_out ={"1","2","3","4"};

        for (int letter_number=0; letter_number<kuozengData.size(); letter_number++)
        {
            for(int target_number=1; target_number<=4; target_number++)
            {
                //判断靶基因中是否包含报告基因
                if(targetTable[QString::number(target_number)]=="")
                {
                    continue;
                }

                for (int cycles_number=0; cycles_number<kuozengData[0].size(); cycles_number++)
                {
                    //插入反应孔
                    cell = sheet->Cell(rows,0);
                    cell->SetWString(reinterpret_cast<const wchar_t *>(QString::number(letter_number+1).utf16()));

                    //插入反应孔位置
                    cell = sheet->Cell(rows,1);
                    cell->SetWString(reinterpret_cast<const wchar_t *>(reactionPlace[letter_number].utf16()));

                    //插入循环数
                    cell = sheet->Cell(rows,2);
                    cell->SetWString(reinterpret_cast<const wchar_t *>(QString::number(cycles_number+1).utf16()));

                    //插入基因名称
                    cell = sheet->Cell(rows,3);
                    cell->SetWString(reinterpret_cast<const wchar_t *>(targetTable.value(QString::number(target_number)).utf16()));

                    //插入Rn
                    cell = sheet->Cell(rows,4);
                    cell->SetWString(reinterpret_cast<const wchar_t *>(kuozengData[letter_number][cycles_number].value(QString::number(target_number)).utf16()));

                    //插入ΔRn
                    cell = sheet->Cell(rows,5);
                    cell->SetWString(reinterpret_cast<const wchar_t *>(kuozengData[letter_number][cycles_number].value(QString::number(target_number)).utf16()));

                    //插入Ct
                    QString target_name = targetTable.value(QString::number(target_number));
                    cell = sheet->Cell(rows,6);
                    cell->SetWString(reinterpret_cast<const wchar_t *>(ctInfo[letter_number][Target_number.value(target_name)].utf16()));
                    //插入完一行数据，行数加1
                    rows++;
                }
            }
            // 休眠
            this->sleep(EXPORT_SLEEP_TIME);
        }
    }

    LOG << "扩增函数结束";

    //保存文件
    if(!e.SaveAs(name.c_str()))
    {
        return false;
    }

    return true;
}

//将qstring转wchar_t

const wchar_t *ExportFileService:: str2char(QString str)
{
    const wchar_t* wstr = reinterpret_cast<const wchar_t *>(str.utf16());
    return wstr;
}


//处理样本信息的样本孔
QList<QHash<QString,QString>> ExportFileService::disposeReactionWells(Sample sampleList[96],Target targetList[96][20])
{
    vector<QString> index = {"A","B","C","D","E","F","G","H"};
    QHash<QString,vector<QString>> sampleInfo;
    QList<QHash<QString,QString>> reactionInfo;

    //生成样本信息查询表
    int reactionNum=1;
    for (int i=0; i<8; i++)
    {
        int num = 1;
        for (int j=i; j<96; j+=8)
        {
            vector<QString> tmp;
            tmp.push_back(sampleList[j].name);
            tmp.push_back(sampleList[j].color_value);
            tmp.push_back(QString::number(reactionNum));

            sampleInfo.insert(index[i]+QString::number(num),tmp);
            reactionNum += 1;
            num += 1;
        }

    }


    //生成反应孔信息
    for (int i=0; i<8; i++)
    {
        int num = 1;
        for (int j=i; j<96; j+=8)
        {
            for(int k=0; k<4; k++)
            {
                //                if(targetList[j][k].name != "null")
                //                {
                QHash<QString,QString> tmp;

                tmp.insert("num",sampleInfo.value(index[i]+QString::number(num))[2]);
                tmp.insert("place",index[i]+QString::number(num));
                tmp.insert("sampleName",sampleInfo.value(index[i]+QString::number(num))[0]);
                tmp.insert("sampleColor",sampleInfo.value(index[i]+QString::number(num))[1]);
                tmp.insert("targetName",targetList[j][k].name);
                tmp.insert("targetColor",targetList[j][k].color);
                tmp.insert("task",targetList[j][k].type);
                tmp.insert("reporter",targetList[j][k].reporter);
                tmp.insert("quencher",targetList[j][k].quencher);
                tmp.insert("quantity",targetList[j][k].quantity);
                tmp.insert("explain",targetList[j][k].explain);

                reactionInfo.append(tmp);
                //                }

            }

            num += 1;

            // 休眠
            this->sleep(EXPORT_SLEEP_TIME);
        }

    }

    return reactionInfo;
}

/* 休眠函数 */
void ExportFileService::sleep(int msec){
    QTime dieTime = QTime::currentTime().addMSecs(msec);
    while( QTime::currentTime() < dieTime)
        QCoreApplication::processEvents(QEventLoop::AllEvents, 100);
}
